package me.zhangsanfeng.frame.util;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

/**
 * 常见的辅助类
 */
public final class DataUtil{
    private static final char UNDERLINE='_';

    /**
     * 十进制字节数组转十六进制字符串
     * @param b
     * @return
     */
    public static final String byte2hex(byte[] b){ // 一个字节数，转成16进制字符串
        StringBuilder hs=new StringBuilder(b.length*2);
        String stmp="";
        for(int n=0;n<b.length;n++){
            // 整数转成十六进制表示
            stmp=Integer.toHexString(b[n]&0XFF);
            if(stmp.length()==1)
                hs.append("0").append(stmp);
            else
                hs.append(stmp);
        }
        return hs.toString(); // 转成大写
    }

    /**
     * 十六进制字符串转十进制字节数组
     * @param
     * @return
     */
    public static final byte[] hex2byte(String hs){
        byte[] b=hs.getBytes();
        if((b.length%2)!=0)
            throw new IllegalArgumentException("长度不是偶数");
        byte[] b2=new byte[b.length/2];
        for(int n=0;n<b.length;n+=2){
            String item=new String(b,n,2);
            // 两位一组，表示一个字节,把这样表示的16进制字符串，还原成一个十进制字节
            b2[n/2]=(byte)Integer.parseInt(item,16);
        }
        return b2;
    }

    /**
     * 这个方法可以通过与某个类的class文件的相对路径来获取文件或目录的绝对路径。 通常在程序中很难定位某个相对路径，特别是在B/S应用中。
     * 通过这个方法，我们可以根据我们程序自身的类文件的位置来定位某个相对路径。 比如：某个txt文件相对于程序的Test类文件的路径是../../resource/test.txt，
     * 那么使用本方法Path.getFullPathRelateClass("../../resource/test.txt",Test.class) 得到的结果是txt文件的在系统中的绝对路径。
     * @param relatedPath 相对路径
     * @param cls 用来定位的类
     * @return 相对路径所对应的绝对路径
     * @throws IOException 因为本方法将查询文件系统，所以可能抛出IO异常
     */
    public static final String getFullPathRelateClass(String relatedPath,Class<?> cls){
        String path=null;
        if(relatedPath==null){
            throw new NullPointerException();
        }
        String clsPath=getPathFromClass(cls);
        File clsFile=new File(clsPath);
        String tempPath=clsFile.getParent()+File.separator+relatedPath;
        File file=new File(tempPath);
        try{
            path=file.getCanonicalPath();
        }catch(IOException e){
            e.printStackTrace();
        }
        return path;
    }

    /**
     * 获取class文件所在绝对路径
     * @param cls
     * @return
     * @throws IOException
     */
    public static final String getPathFromClass(Class<?> cls){
        String path=null;
        if(cls==null){
            throw new NullPointerException();
        }
        URL url=getClassLocationURL(cls);
        if(url!=null){
            path=url.getPath();
            if("jar".equalsIgnoreCase(url.getProtocol())){
                try{
                    path=new URL(path).getPath();
                }catch(MalformedURLException e){
                }
                int location=path.indexOf("!/");
                if(location!=-1){
                    path=path.substring(0,location);
                }
            }
            File file=new File(path);
            try{
                path=file.getCanonicalPath();
            }catch(IOException e){
                e.printStackTrace();
            }
        }
        return path;
    }

    /**
     * 判断对象是否Empty(null或元素为0)<br>
     * 实用于对如下对象做判断:String Collection及其子类 Map及其子类
     * @param pObj 待检查对象
     * @return boolean 返回的布尔值
     */
    public static final boolean isEmpty(Object pObj){
        if(pObj==null)
            return true;
        if(pObj=="")
            return true;
        if(pObj instanceof String){
            if(((String)pObj).trim().length()==0){
                return true;
            }
        }else if(pObj instanceof Collection<?>){
            if(((Collection<?>)pObj).size()==0){
                return true;
            }
        }else if(pObj instanceof Map<?,?>){
            if(((Map<?,?>)pObj).size()==0){
                return true;
            }
        }
        return false;
    }

    /**
     * 判断对象是否为NotEmpty(!null或元素>0)<br>
     * 实用于对如下对象做判断:String Collection及其子类 Map及其子类
     * @param pObj 待检查对象
     * @return boolean 返回的布尔值
     */
    public static final boolean isNotEmpty(Object pObj){
        if(pObj==null)
            return false;
        if(pObj=="")
            return false;
        if(pObj instanceof String){
            if(((String)pObj).trim().length()==0){
                return false;
            }
        }else if(pObj instanceof Collection<?>){
            if(((Collection<?>)pObj).size()==0){
                return false;
            }
        }else if(pObj instanceof Map<?,?>){
            if(((Map<?,?>)pObj).size()==0){
                return false;
            }
        }
        return true;
    }

    /**
     * JS输出含有\n的特殊处理
     * @param pStr
     * @return
     */
    public static final String replace4JsOutput(String pStr){
        pStr=pStr.replace("\r\n","<br/>&nbsp;&nbsp;");
        pStr=pStr.replace("\t","&nbsp;&nbsp;&nbsp;&nbsp;");
        pStr=pStr.replace(" ","&nbsp;");
        return pStr;
    }

    /**
     * 分别去空格
     * @param paramArray
     * @return
     */
    public static final String[] trim(String[] paramArray){
        if(ArrayUtils.isEmpty(paramArray)){
            return paramArray;
        }
        String[] resultArray=new String[paramArray.length];
        for(int i=0;i<paramArray.length;i++){
            String param=paramArray[i];
            resultArray[i]=StringUtils.trim(param);
        }
        return resultArray;
    }

    /**
     * 获取类的class文件位置的URL
     * @param cls
     * @return
     */
    private static URL getClassLocationURL(final Class<?> cls){
        if(cls==null)
            throw new IllegalArgumentException("null input: cls");
        URL result=null;
        final String clsAsResource=cls.getName().replace('.','/').concat(".class");
        final ProtectionDomain pd=cls.getProtectionDomain();
        if(pd!=null){
            final CodeSource cs=pd.getCodeSource();
            if(cs!=null)
                result=cs.getLocation();
            if(result!=null){
                if("file".equals(result.getProtocol())){
                    try{
                        if(result.toExternalForm().endsWith(".jar")||result.toExternalForm().endsWith(".zip"))
                            result=new URL("jar:".concat(result.toExternalForm()).concat("!/").concat(
                                    clsAsResource));
                        else if(new File(result.getFile()).isDirectory())
                            result=new URL(result,clsAsResource);
                    }catch(MalformedURLException ignore){
                    }
                }
            }
        }
        if(result==null){
            final ClassLoader clsLoader=cls.getClassLoader();
            result=clsLoader!=null ? clsLoader.getResource(clsAsResource)
                    : ClassLoader.getSystemResource(clsAsResource);
        }
        return result;
    }

    /** 初始化设置默认值 */
    public static final <K> K ifNull(K k,K defaultValue){
        if(k==null){
            return defaultValue;
        }
        return k;
    }

    /**
     * 驼峰格式字符串转换为下划线格式字符串
     * @param param
     * @return
     */
    public static String camelToUnderline(String param){
        if(param==null||"".equals(param.trim())){
            return "";
        }
        int len=param.length();
        StringBuilder sb=new StringBuilder(len);
        for(int i=0;i<len;i++){
            char c=param.charAt(i);
            if(Character.isUpperCase(c)){
                sb.append(UNDERLINE);
                sb.append(Character.toLowerCase(c));
            }else{
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * 下划线格式字符串转换为驼峰格式字符串
     * @param param
     * @return
     */
    public static String underlineToCamel(String param){
        if(param==null||"".equals(param.trim())){
            return "";
        }
        StringBuilder sb=new StringBuilder(param);
        Matcher mc=Pattern.compile("_").matcher(param);
        int i=0;
        while(mc.find()){
            int position=mc.end()-(i++);
            sb.replace(position-1,position+1,sb.substring(position,position+1).toUpperCase());
        }
        return sb.toString();
    }

    /**
     * 正则表达式匹配两个指定字符串中间的内容
     * @param soap "abc(.*?)abc"
     * @return
     */
    public static List<String> getSubUtil(String soap,String rgex){
        List<String> list=new ArrayList<String>();
        Pattern pattern=Pattern.compile(rgex);// 匹配的模式
        Matcher m=pattern.matcher(soap);
        while(m.find()){
            int i=1;
            list.add(m.group(i));
            i++;
        }
        return list;
    }

    /**
     * 返回单个字符串，若匹配到多个的话就返回第一个，方法与getSubUtil一样
     * @param soap
     * @param rgex
     * @return
     */
    public static String getSubUtilSimple(String soap,String rgex){
        Pattern pattern=Pattern.compile(rgex);// 匹配的模式
        Matcher m=pattern.matcher(soap);
        while(m.find()){
            return m.group(1);
        }
        return "";
    }

    /**
     * 返回是否是数字
     * @param str
     * @return
     */
    public static boolean isNumeric(String str){
        Pattern pattern=Pattern.compile("[0-9]*");
        Matcher isNum=pattern.matcher(str);
        if(!isNum.matches()){
            return false;
        }
        return true;
    }

}